package com.programs.waw;

public class FastwebTelseyAlgorithm {

	private String ssid;
	private String v;

	public FastwebTelseyAlgorithm(String ssid) {

		this.ssid = ssid;
		v = new String(
				"ZVUZVUVZYWXWYXWWWYWUWZXVUYUVVYVUWYWWXVXYYVYXZVZZWVUZVUVVYWVXXXZWYYZYZVYUWZUZWVXZZWWYWXVYUYYXXUZXYXUUXWVVWVWZVXYXUWXYUUWWUUUZVVVYYUWWXXXUUWYVZZZUUYZUVVZWWWZVXXWXVUWYVZWZUVYUVVVYWWWWXXXXZYUVYUZZVUZUUVZVWWYWXYYXYXVZZZVYXUVZXVUYYWWZYXXVWYXUWXZVXVWXZUVWZXYVUWXU");
	}

	public String calcola() {

		int s1 = 0;
		int s2 = 0;
		String s1String;
		String s2String;

		long[] k = vectorToLongArray(calcolaVettore(ssid, v));

		for (int i = 0; i < k.length; i++) {
			s1 = hashWord(k, 0, i, s1);
		}

		s1String = Integer.toHexString(s1);

		while (s1String.length() < 8)
			s1String = "0" + s1String;

		for (int i = 0; i < 64; i++) {
			if (i < 8) {
				k[i] = k[i] << 3;
				continue;
			}
			if (i < 16) {
				k[i] = k[i] >>> 5;
				continue;
			}
			if (i < 32) {
				k[i] = k[i] >>> 2;
				continue;
			}
			k[i] = k[i] << 7;
		}

		for (int i = 0; i < k.length; i++) {
			s2 = hashWord(k, 0, i, s2);
		}

		s2String = Integer.toHexString(s2);

		while (s2String.length() < 8)
			s2String = "0" + s2String;

		return s1String.substring(3) + s2String.substring(0, 5);

	}

	private String calcolaVettore(String ssid, String vector) {

		char c = 'U';

		for (int i = 0; i < 12; i += 2) {
			vector = vector.replaceAll(c + "", ssid.substring(i, i + 2));
			c += 1;
		}

		System.out.println(vector.length());

		return vector;

	}

	private long[] vectorToLongArray(String vector) {

		int j = 0;
		long[] k = new long[64];

		for (int i = 0; i < 512; i += 8) {
			k[j] = Long.parseLong((vector.substring(i, i + 8)), 16);
			j += 1;
		}

		return k;
	}

	@SuppressWarnings("fallthrough")
	private int hashWord(long[] k, int offset, int length, int initval) {

		int a, b, c;
		int i = offset;

		a = b = c = 0xdeadbeef + (length << 2) + initval;

		while (length > 3) {
			a += k[i];
			b += k[i + 1];
			c += k[i + 2];

			{
				a -= c;
				a ^= (c << 4) | (c >>> -4);
				c += b;
				b -= a;
				b ^= (a << 6) | (a >>> -6);
				a += c;
				c -= b;
				c ^= (b << 8) | (b >>> -8);
				b += a;
				a -= c;
				a ^= (c << 16) | (c >>> -16);
				c += b;
				b -= a;
				b ^= (a << 19) | (a >>> -19);
				a += c;
				c -= b;
				c ^= (b << 4) | (b >>> -4);
				b += a;
			}

			length -= 3;
			i += 3;
		}

		switch (length) {

		case 3:
			c += k[i + 2];
		case 2:
			b += k[i + 1];
		case 1:
			a += k[i + 0];

			{
				c ^= b;
				c -= (b << 14) | (b >>> -14);
				a ^= c;
				a -= (c << 11) | (c >>> -11);
				b ^= a;
				b -= (a << 25) | (a >>> -25);
				c ^= b;
				c -= (b << 16) | (b >>> -16);
				a ^= c;
				a -= (c << 4) | (c >>> -4);
				b ^= a;
				b -= (a << 14) | (a >>> -14);
				c ^= b;
				c -= (b << 24) | (b >>> -24);
			}
		case 0:
			break;
		}

		return c;
	}

}
